/*
	FileName : JT_C_COMM_SM.c
	Description :
		Manage the JT_C host communication state.
	
	Created on 2017.11.18 by WFL.

	Revision History:

*/


/* Includes ------------------------------------------------------------------*/
#include "JT_C_COMM_SM.h"
#include "JT_C_REC_Item.h"
#include "JT_C_TAX.h"
//---------------------------------------------------------------------
JTC_COMM_SM uart1_SM;



//------------------
void JTC_COMM_SM_CopyBoardData(JTC_COMM_SM *sm)
{
	uint16_t k;
	
	k = StsCtrl.readyIndex;
	
	if(STS_FRAME_ZJBDataErrorCheck(sm->JMA1_DATA))
		StsCtrl.BoardDataValid |= (1 << 3);
	else
		StsCtrl.BoardDataValid &= (~(1 << 3));
	
	if(STS_FRAME_ZJBDataErrorCheck(sm->JMA2_DATA))
		StsCtrl.BoardDataValid |= (1 << 2);
	else
		StsCtrl.BoardDataValid &= (~(1 << 2));
	
	if(STS_FRAME_ZJBDataErrorCheck(sm->JMB1_DATA))
		StsCtrl.BoardDataValid |= (1 << 1);
	else
		StsCtrl.BoardDataValid &= (~(1 << 1));
	if(STS_FRAME_ZJBDataErrorCheck(sm->JMB2_DATA))
		StsCtrl.BoardDataValid |= (1 << 0);
	else
		StsCtrl.BoardDataValid &= (~(1 << 0));
	
	STS_FRAME_setBdValidBit_board(&StsFrame[k],&StsCtrl);
	
	STS_FRAME_copyIn_JMA1(&StsFrame[k],sm->JMA1_DATA);
	STS_FRAME_copyIn_JMA2(&StsFrame[k],sm->JMA2_DATA);
	STS_FRAME_copyIn_JMB1(&StsFrame[k],sm->JMB1_DATA);
	STS_FRAME_copyIn_JMB2(&StsFrame[k],sm->JMB2_DATA);
	STS_FRAME_copyIn_LJB(&StsFrame[k],sm->LJB_DATA);
	
	STS_FRAME_setCRC(&StsFrame[k]);
	
	StsCtrl.readyIndex = STS_FRAME_indexAdd(StsCtrl.readyIndex);
		
}
//------------------------------------------------

void JTC_COMM_SM_init(JTC_COMM_SM *sm)
{
	sm->currState = JTC_COMM_SM_STATE_IDEL;
	sm->monitorTick = 0;
	sm->smTick = 0;
	sm->sm_time = 0;
	
	sm->ZJA_errCnt = 0;
	sm->ZJB_errCnt = 0;
	sm->LJB_errCnt = 0;
	sm->JLB_Xfer_cnt = 0;
	
	sm->ex_VersionFlag = 0;
	sm->in_VersionFlag = 0;
	sm->JW_Flag = 0;
	
	//----------------------
	sm->uartReceiveFlag = 0;
	sm->uartReceiveDataLen = 0;
	
	sm->uartTransmitFlag = 0;
	sm->uartTransmitDataLen = 0;
	return;
}

void JTC_COMM_SM_stepTick(JTC_COMM_SM *sm)
{
	sm->smTick++;
	return;
}
//-----------------------------------------------------
void JTC_COMM_SM_setMonitortick(JTC_COMM_SM *sm)
{
	sm->monitorTick = sm->smTick;
	return;
}

uint32_t JTC_COMM_SM_tickElapsed(JTC_COMM_SM *sm)
{
	if(sm->smTick < sm->monitorTick)
		return 0xFFFFFFFF;
	else
		return (sm->smTick - sm->monitorTick);
}

void JTC_COMM_SM_stateSwitch(JTC_COMM_SM *sm,uint8_t newState)
{
	JTC_COMM_SM_setMonitortick(sm);
	JTC_COMM_SM_clearRxFlag(sm);
	sm->currState = newState;
	return;
}
/// ------------------------------------------------------------------
/// call by user task circularly
/// ------------------------------------------------------------------
void JTC_COMM_SM_main(JTC_COMM_SM *sm)
{
	uint16_t i;
	uint8_t data[8],*ptr;
	switch(sm->currState){
		
		case JTC_COMM_SM_STATE_IDEL:
			if(StsCtrl.adcCreatIndex != StsCtrl.readyIndex)
				sm->currState = JTC_COMM_SM_STATE_i_JMA1;
			else if(StsCtrl.readyIndex != StsCtrl.handledIndex)
				sm->currState = JTC_COMM_SM_STATE_BROADCAST;
			else if(sm->JW_Flag)
				sm->currState = JTC_COMM_SM_STATE_i_JW;
			else if(sm->smTick > 32000 && !sm->ex_VersionFlag)
				sm->currState = JTC_COMM_SM_STATE_i_VER_BIOS_ZKA;
			else if(sm->smTick > 34000 && !sm->in_VersionFlag)
				sm->currState = JTC_COMM_SM_STATE_i_VER_APP_ZKA;
			break;
			
		//--------------------------------	
		case JTC_COMM_SM_STATE_i_JMA1:
			if(sm->JMA1_errCnt > 5)
			{
				JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_i_JMA2);
				break;
			}
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_JMA1,
								JTC_COMM_CMDTYPE_WORK_INFO,
								JTC_COMM_CMD_INQUIRY_WORK_INFO,
								0,
								1);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_JMA1);
			break;
		case JTC_COMM_SM_STATE_w_JMA1:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_JMA1,CMD_ACK_WORK_INFO,ACK_LEN_CTRL)){
				
				//copy data
				for(i=0;i<sm->uartReceiveDataLen;i++)
					sm->JMA1_DATA[i] = sm->uartReceiveData[i];
				//set board valid
				StsCtrl.BoardDisconnected &= (~(1 << 3));
				sm->JMA1_errCnt = 0;
				sm->currState = JTC_COMM_SM_STATE_i_JMA2;
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_500ms)
			{
				//set boart unvalid
				sm->JMA1_errCnt++;
				if(sm->JMA1_errCnt >0)
					StsCtrl.BoardDisconnected |= (1 << 3);
				sm->currState = JTC_COMM_SM_STATE_i_JMA2;
			}
			break;
			
		case JTC_COMM_SM_STATE_i_JMA2:
			if(sm->JMA2_errCnt > 5)
			{
				JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_i_JMB1);
				break;
			}
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_JMA2,
								JTC_COMM_CMDTYPE_WORK_INFO,
								JTC_COMM_CMD_INQUIRY_WORK_INFO,
								0,
								1);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_JMA2);
			break;
		case JTC_COMM_SM_STATE_w_JMA2:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_JMA2,CMD_ACK_WORK_INFO,ACK_LEN_CTRL)){
				
				//copy data
				for(i=0;i<sm->uartReceiveDataLen;i++)
					sm->JMA2_DATA[i] = sm->uartReceiveData[i];
				//set board valid
				StsCtrl.BoardDisconnected &= (~(1 << 2));
				sm->JMA2_errCnt = 0;
				sm->currState = JTC_COMM_SM_STATE_i_JMB1;
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_500ms)
			{
				//set boart unvalid
				sm->JMA2_errCnt++;
				if(sm->JMA2_errCnt >0)
					StsCtrl.BoardDisconnected |= (1 << 2);
				sm->currState = JTC_COMM_SM_STATE_i_JMB1;
			}
			break;
			
		case JTC_COMM_SM_STATE_i_JMB1:
			if(sm->JMB1_errCnt > 5)
			{
				JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_i_JMB2);
				break;
			}
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_JMB1,
								JTC_COMM_CMDTYPE_WORK_INFO,
								JTC_COMM_CMD_INQUIRY_WORK_INFO,
								0,
								1);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_JMB1);
			break;
		case JTC_COMM_SM_STATE_w_JMB1:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_JMB1,CMD_ACK_WORK_INFO,ACK_LEN_CTRL)){
				
				//copy data
				for(i=0;i<sm->uartReceiveDataLen;i++)
					sm->JMB1_DATA[i] = sm->uartReceiveData[i];
				//set board valid
				StsCtrl.BoardDisconnected &= (~(1 << 1));
				sm->JMB1_errCnt = 0;
				sm->currState = JTC_COMM_SM_STATE_i_JMB2;
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_500ms)
			{
				//set boart unvalid
				sm->JMB1_errCnt++;
				if(sm->JMB1_errCnt >0)
					StsCtrl.BoardDisconnected |= (1 << 1);
				sm->currState = JTC_COMM_SM_STATE_i_JMB2;
			}
			break;
			
		case JTC_COMM_SM_STATE_i_JMB2:
			if(sm->JMB2_errCnt > 5)
			{
				JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_i_LJB);
				break;
			}
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_JMB2,
								JTC_COMM_CMDTYPE_WORK_INFO,
								JTC_COMM_CMD_INQUIRY_WORK_INFO,
								0,
								1);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_JMB2);
			break;
		case JTC_COMM_SM_STATE_w_JMB2:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_JMB2,CMD_ACK_WORK_INFO,ACK_LEN_CTRL)){
				
				//copy data
				for(i=0;i<sm->uartReceiveDataLen;i++)
					sm->JMB2_DATA[i] = sm->uartReceiveData[i];
				//set board valid
				StsCtrl.BoardDisconnected &= (~(1 << 0));
				sm->JMB2_errCnt = 0;
				sm->currState = JTC_COMM_SM_STATE_i_LJB;
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_500ms)
			{
				//set boart unvalid
				sm->JMB2_errCnt++;
				if(sm->JMB2_errCnt >0)
					StsCtrl.BoardDisconnected |= (1 << 0);
				sm->currState = JTC_COMM_SM_STATE_i_LJB;
			}
			break;
				
		case JTC_COMM_SM_STATE_i_LJB:
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_LJB,
								JTC_COMM_CMDTYPE_WORK_INFO,
								JTC_COMM_CMD_INQUIRY_WORK_INFO,
								0,
								1);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_LJB);
			break;
		case JTC_COMM_SM_STATE_w_LJB:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_LJB,CMD_ACK_WORK_INFO,ACK_LEN_110V+1)){
				
				sm->JW_Flag = sm->uartReceiveData[ACK_LEN_110V];
				//copy data
				for(i=0;i<sm->uartReceiveDataLen-1;i++)
					sm->LJB_DATA[i] = sm->uartReceiveData[i];
				//set board valid
				sm->LJB_errCnt = 0;
				StsCtrl.BoardDisconnected &= (~(1 << 5));
				sm->currState = JTC_COMM_SM_STATE_IDEL;
				JTC_COMM_SM_CopyBoardData(sm);
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_100ms)
			{
				//set boart unvalid
				sm->LJB_errCnt++;
				if(sm->LJB_errCnt >4)
					StsCtrl.BoardDisconnected |= (1 << 5);
				sm->currState = JTC_COMM_SM_STATE_IDEL;
				JTC_COMM_SM_CopyBoardData(sm);
			}
			break;
			
		//-------------------------------------
		case JTC_COMM_SM_STATE_BROADCAST:
			
			data[0] = (sm->sm_time >> 0) & 0xFF;
			data[1] = (sm->sm_time >> 8) & 0xFF;
			data[2] = (sm->sm_time >>16) & 0xFF;
			data[3] = (sm->sm_time >>24) & 0xFF;
			JTC_TAX_getKmPost(&data[4]);
		
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_LJB,
								JTC_COMM_CMDTYPE_WORK_INFO,
								JTC_COMM_CMD_TIME_BROAD_CAST,
								data,
								7);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_s_REC);
			sm->JLB_Xfer_cnt = 0;
			break;
		
		case JTC_COMM_SM_STATE_s_REC:
			sm->JLB_Xfer_cnt++;
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_JLB_MAIN,
								JTC_COMM_CMDTYPE_WORK_INFO,
								JTC_COMM_CMD_XFER_STATUS_INFO,
								(uint8_t*)(&StsFrame[StsCtrl.handledIndex]),
								STS_FRAME_SIZE);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_REC);
			break;
		
		case JTC_COMM_SM_STATE_w_REC:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_JLB_MAIN,CMD_ACK_STATUS_INFO,2)){
				
				StsCtrl.handledIndex = STS_FRAME_indexAdd(StsCtrl.handledIndex);
				sm->currState = JTC_COMM_SM_STATE_IDEL;
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_100ms)
			{
				if(sm->JLB_Xfer_cnt >= 3)
				{
					StsCtrl.handledIndex = STS_FRAME_indexAdd(StsCtrl.handledIndex);
					sm->currState = JTC_COMM_SM_STATE_IDEL;
				}
				else
				{
					sm->currState = JTC_COMM_SM_STATE_s_REC;
				}
			}
			break;
			
		//--------------BIOS verison--------------------------------------
		case JTC_COMM_SM_STATE_i_VER_BIOS_ZKA:
			data[0] = 0;
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_ZKA,
								JTC_COMM_CMDTYPE_FIRMWARE,
								JTC_COMM_CMD_INQUIRY_Ex_VERSION,
								data,
								1);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_VER_BIOS_ZKA);
			break;
		case JTC_COMM_SM_STATE_w_VER_BIOS_ZKA:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_ZKA,CMD_ACK_VERSION,9)){
				
				//copy data
				ptr = (uint8_t*)(&sm->SoftVersion[JTC_COMM_VerIndex_ZKA_BIOS]);
				for(i=0;i<sm->uartReceiveDataLen;i++)
					ptr[i] = sm->uartReceiveData[i];
				sm->currState = JTC_COMM_SM_STATE_i_VER_BIOS_JMA1;
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_100ms)
			{
				sm->currState = JTC_COMM_SM_STATE_i_VER_BIOS_JMA1;
			}
			break;
		case JTC_COMM_SM_STATE_i_VER_BIOS_JMA1:
			data[0] = 0;
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_JMA1,
								JTC_COMM_CMDTYPE_FIRMWARE,
								JTC_COMM_CMD_INQUIRY_Ex_VERSION,
								data,
								1);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_VER_BIOS_JMA1);
			break;
		case JTC_COMM_SM_STATE_w_VER_BIOS_JMA1:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_JMA1,CMD_ACK_VERSION,9)){
				
				//copy data
				ptr = (uint8_t*)(&sm->SoftVersion[JTC_COMM_VerIndex_JMA1_BIOS]);
				for(i=0;i<sm->uartReceiveDataLen;i++)
					ptr[i] = sm->uartReceiveData[i];
				sm->currState = JTC_COMM_SM_STATE_i_VER_BIOS_JMA2;
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_100ms)
			{
				sm->currState = JTC_COMM_SM_STATE_i_VER_BIOS_JMA2;
			}
			break;
		case JTC_COMM_SM_STATE_i_VER_BIOS_JMA2:
			data[0] = 0;
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_JMA2,
								JTC_COMM_CMDTYPE_FIRMWARE,
								JTC_COMM_CMD_INQUIRY_Ex_VERSION,
								data,
								1);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_VER_BIOS_JMA2);
			break;
		case JTC_COMM_SM_STATE_w_VER_BIOS_JMA2:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_JMA2,CMD_ACK_VERSION,9)){
				
				//copy data
				ptr = (uint8_t*)(&sm->SoftVersion[JTC_COMM_VerIndex_JMA2_BIOS]);
				for(i=0;i<sm->uartReceiveDataLen;i++)
					ptr[i] = sm->uartReceiveData[i];
				sm->currState = JTC_COMM_SM_STATE_i_VER_BIOS_ZKB;
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_100ms)
			{
				sm->currState = JTC_COMM_SM_STATE_i_VER_BIOS_ZKB;
			}
			break;
		case JTC_COMM_SM_STATE_i_VER_BIOS_ZKB:
			data[0] = 0;
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_ZKB,
								JTC_COMM_CMDTYPE_FIRMWARE,
								JTC_COMM_CMD_INQUIRY_Ex_VERSION,
								data,
								1);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_VER_BIOS_ZKB);
			break;
		case JTC_COMM_SM_STATE_w_VER_BIOS_ZKB:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_ZKB,CMD_ACK_VERSION,9)){
				
				//copy data
				ptr = (uint8_t*)(&sm->SoftVersion[JTC_COMM_VerIndex_ZKB_BIOS]);
				for(i=0;i<sm->uartReceiveDataLen;i++)
					ptr[i] = sm->uartReceiveData[i];
				sm->currState = JTC_COMM_SM_STATE_i_VER_BIOS_JMB1;
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_100ms)
			{
				sm->currState = JTC_COMM_SM_STATE_i_VER_BIOS_JMB1;
			}
			break;
		case JTC_COMM_SM_STATE_i_VER_BIOS_JMB1:
			data[0] = 0;
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_JMB1,
								JTC_COMM_CMDTYPE_FIRMWARE,
								JTC_COMM_CMD_INQUIRY_Ex_VERSION,
								data,
								1);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_VER_BIOS_JMB1);
			break;
		case JTC_COMM_SM_STATE_w_VER_BIOS_JMB1:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_JMB1,CMD_ACK_VERSION,9)){
				
				//copy data
				ptr = (uint8_t*)(&sm->SoftVersion[JTC_COMM_VerIndex_JMB1_BIOS]);
				for(i=0;i<sm->uartReceiveDataLen;i++)
					ptr[i] = sm->uartReceiveData[i];
				sm->currState = JTC_COMM_SM_STATE_i_VER_BIOS_JMB2;
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_100ms)
			{
				sm->currState = JTC_COMM_SM_STATE_i_VER_BIOS_JMB2;
			}
			break;
		case JTC_COMM_SM_STATE_i_VER_BIOS_JMB2:
			data[0] = 0;
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_JMB2,
								JTC_COMM_CMDTYPE_FIRMWARE,
								JTC_COMM_CMD_INQUIRY_Ex_VERSION,
								data,
								1);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_VER_BIOS_JMB2);
			break;
		case JTC_COMM_SM_STATE_w_VER_BIOS_JMB2:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_JMB2,CMD_ACK_VERSION,9)){
				
				//copy data
				ptr = (uint8_t*)(&sm->SoftVersion[JTC_COMM_VerIndex_JMB2_BIOS]);
				for(i=0;i<sm->uartReceiveDataLen;i++)
					ptr[i] = sm->uartReceiveData[i];
				sm->currState = JTC_COMM_SM_STATE_i_VER_BIOS_LJB;
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_100ms)
			{
				sm->currState = JTC_COMM_SM_STATE_i_VER_BIOS_LJB;
			}
			break;
		case JTC_COMM_SM_STATE_i_VER_BIOS_LJB:
			data[0] = 0;
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_LJB,
								JTC_COMM_CMDTYPE_FIRMWARE,
								JTC_COMM_CMD_INQUIRY_Ex_VERSION,
								data,
								1);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_VER_BIOS_LJB);
			break;
		case JTC_COMM_SM_STATE_w_VER_BIOS_LJB:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_LJB,CMD_ACK_VERSION,9)){
				
				//copy data
				ptr = (uint8_t*)(&sm->SoftVersion[JTC_COMM_VerIndex_LJB_BIOS]);
				for(i=0;i<sm->uartReceiveDataLen;i++)
					ptr[i] = sm->uartReceiveData[i];
				sm->ex_VersionFlag = 1;
				sm->currState = JTC_COMM_SM_STATE_IDEL;
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_100ms)
			{
				sm->ex_VersionFlag = 1;
				sm->currState = JTC_COMM_SM_STATE_IDEL;
			}
			break;
		
		//-----------------APP version-----------------------------------
		case JTC_COMM_SM_STATE_i_VER_APP_ZKA:
			data[0] = 1;
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_ZKA,
								JTC_COMM_CMDTYPE_FIRMWARE,
								JTC_COMM_CMD_INQUIRY_Ex_VERSION,
								data,
								1);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_VER_APP_ZKA);
			break;
		case JTC_COMM_SM_STATE_w_VER_APP_ZKA:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_ZKA,CMD_ACK_VERSION,9)){
				
				//copy data
				ptr = (uint8_t*)(&sm->SoftVersion[JTC_COMM_VerIndex_ZKA_APP]);
				for(i=0;i<sm->uartReceiveDataLen;i++)
					ptr[i] = sm->uartReceiveData[i];
				sm->currState = JTC_COMM_SM_STATE_i_VER_APP_JMA1;
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_100ms)
			{
				sm->currState = JTC_COMM_SM_STATE_i_VER_APP_JMA1;
			}
			break;
		case JTC_COMM_SM_STATE_i_VER_APP_JMA1:
			data[0] = 1;
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_JMA1,
								JTC_COMM_CMDTYPE_FIRMWARE,
								JTC_COMM_CMD_INQUIRY_Ex_VERSION,
								data,
								1);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_VER_APP_JMA1);
			break;
		case JTC_COMM_SM_STATE_w_VER_APP_JMA1:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_JMA1,CMD_ACK_VERSION,9)){
				
				//copy data
				ptr = (uint8_t*)(&sm->SoftVersion[JTC_COMM_VerIndex_JMA1_APP]);
				for(i=0;i<sm->uartReceiveDataLen;i++)
					ptr[i] = sm->uartReceiveData[i];
				sm->currState = JTC_COMM_SM_STATE_i_VER_APP_JMA2;
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_100ms)
			{
				sm->currState = JTC_COMM_SM_STATE_i_VER_APP_JMA2;
			}
			break;
		case JTC_COMM_SM_STATE_i_VER_APP_JMA2:
			data[0] = 1;
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_JMA2,
								JTC_COMM_CMDTYPE_FIRMWARE,
								JTC_COMM_CMD_INQUIRY_Ex_VERSION,
								data,
								1);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_VER_APP_JMA2);
			break;
		case JTC_COMM_SM_STATE_w_VER_APP_JMA2:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_JMA2,CMD_ACK_VERSION,9)){
				
				//copy data
				ptr = (uint8_t*)(&sm->SoftVersion[JTC_COMM_VerIndex_JMA2_APP]);
				for(i=0;i<sm->uartReceiveDataLen;i++)
					ptr[i] = sm->uartReceiveData[i];
				sm->currState = JTC_COMM_SM_STATE_i_VER_APP_ZKB;
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_100ms)
			{
				sm->currState = JTC_COMM_SM_STATE_i_VER_APP_ZKB;
			}
			break;
		case JTC_COMM_SM_STATE_i_VER_APP_ZKB:
			data[0] = 1;
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_ZKB,
								JTC_COMM_CMDTYPE_FIRMWARE,
								JTC_COMM_CMD_INQUIRY_Ex_VERSION,
								data,
								1);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_VER_APP_ZKB);
			break;
		case JTC_COMM_SM_STATE_w_VER_APP_ZKB:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_ZKB,CMD_ACK_VERSION,9)){
				
				//copy data
				ptr = (uint8_t*)(&sm->SoftVersion[JTC_COMM_VerIndex_ZKB_APP]);
				for(i=0;i<sm->uartReceiveDataLen;i++)
					ptr[i] = sm->uartReceiveData[i];
				sm->currState = JTC_COMM_SM_STATE_i_VER_APP_JMB1;
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_100ms)
			{
				sm->currState = JTC_COMM_SM_STATE_i_VER_APP_JMB1;
			}
			break;
		case JTC_COMM_SM_STATE_i_VER_APP_JMB1:
			data[0] = 1;
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_JMB1,
								JTC_COMM_CMDTYPE_FIRMWARE,
								JTC_COMM_CMD_INQUIRY_Ex_VERSION,
								data,
								1);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_VER_APP_JMB1);
			break;
		case JTC_COMM_SM_STATE_w_VER_APP_JMB1:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_JMB1,CMD_ACK_VERSION,9)){
				
				//copy data
				ptr = (uint8_t*)(&sm->SoftVersion[JTC_COMM_VerIndex_JMB1_APP]);
				for(i=0;i<sm->uartReceiveDataLen;i++)
					ptr[i] = sm->uartReceiveData[i];
				sm->currState = JTC_COMM_SM_STATE_i_VER_APP_JMB2;
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_100ms)
			{
				sm->currState = JTC_COMM_SM_STATE_i_VER_APP_JMB2;
			}
			break;
		case JTC_COMM_SM_STATE_i_VER_APP_JMB2:
			data[0] = 1;
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_JMB2,
								JTC_COMM_CMDTYPE_FIRMWARE,
								JTC_COMM_CMD_INQUIRY_Ex_VERSION,
								data,
								1);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_VER_APP_JMB2);
			break;
		case JTC_COMM_SM_STATE_w_VER_APP_JMB2:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_JMB2,CMD_ACK_VERSION,9)){
				
				//copy data
				ptr = (uint8_t*)(&sm->SoftVersion[JTC_COMM_VerIndex_JMB2_APP]);
				for(i=0;i<sm->uartReceiveDataLen;i++)
					ptr[i] = sm->uartReceiveData[i];
				sm->currState = JTC_COMM_SM_STATE_i_VER_APP_LJB;
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_100ms)
			{
				sm->currState = JTC_COMM_SM_STATE_i_VER_APP_LJB;
			}
			break;
		case JTC_COMM_SM_STATE_i_VER_APP_LJB:
			data[0] = 1;
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_LJB,
								JTC_COMM_CMDTYPE_FIRMWARE,
								JTC_COMM_CMD_INQUIRY_Ex_VERSION,
								data,
								1);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_VER_APP_LJB);
			break;
		case JTC_COMM_SM_STATE_w_VER_APP_LJB:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_LJB,CMD_ACK_VERSION,9)){
				
				//copy data
				ptr = (uint8_t*)(&sm->SoftVersion[JTC_COMM_VerIndex_LJB_APP]);
				for(i=0;i<sm->uartReceiveDataLen;i++)
					ptr[i] = sm->uartReceiveData[i];
				
				sm->in_VersionFlag = 1;
				sm->currState = JTC_COMM_SM_STATE_s_VERSION;
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_100ms)
			{
				sm->in_VersionFlag = 1;
				sm->currState = JTC_COMM_SM_STATE_s_VERSION;
			}
			break;
		case JTC_COMM_SM_STATE_s_VERSION:
			ptr = (uint8_t*)(&sm->SoftVersion[JTC_COMM_VerIndex_JLSAM_BIOS]);
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_JLB_MAIN,
								JTC_COMM_CMDTYPE_DEBUG,
								JTC_COMM_CMD_XFER_BOARD_VERSION_INFO,
								ptr,
								JTC_COMM_VERSION_DATALEN);
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_VERSION);
			break;
		case JTC_COMM_SM_STATE_w_VERSION:
			if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_100ms)
			{
				sm->currState = JTC_COMM_SM_STATE_IDEL;
			}
			break;
		//---------------JW data--------------------------------------
		case JTC_COMM_SM_STATE_i_JW:
			JTC_COMM_SM_setTxFrame(sm,
								JTC_COMM_BDADDR_LJB,
								JTC_COMM_CMDTYPE_WORK_INFO,
								JTC_COMM_CMD_INQUIRY_110V_INFO,
								0,
								1);
			sm->JW_Flag = 0;
			JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_JW);
			break;
		case JTC_COMM_SM_STATE_w_JW:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_LJB,CMD_ACK_110V_INFO,0xFFFF)){
				
				JTC_COMM_SM_setTxFrame(sm,
									JTC_COMM_BDADDR_JLB_MAIN,
									JTC_COMM_CMDTYPE_WORK_INFO,
									JTC_COMM_CMD_XFER_JW_INFO,
									sm->uartReceiveData,
									sm->uartReceiveDataLen);
				JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_JW_save);
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_50ms)
			{
				sm->currState = JTC_COMM_SM_STATE_IDEL;
			}
			break;
		case JTC_COMM_SM_STATE_w_JW_save:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_JLB_MAIN,CMD_JW_SAVE_ACK,4)){
				
				JTC_COMM_SM_setTxFrame(sm,
									JTC_COMM_BDADDR_LJB,
									JTC_COMM_CMDTYPE_WORK_INFO,
									CMD_JW_CLEAR,
									sm->uartReceiveData,
									sm->uartReceiveDataLen);
				JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_w_JW_clear);
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_50ms)
			{
				sm->currState = JTC_COMM_SM_STATE_IDEL;
			}
			break;
		case JTC_COMM_SM_STATE_w_JW_clear:
			if(JTC_COMM_SM_receiveNewFrame(sm,JTC_COMM_BDADDR_LJB,CMD_JW_CLEAR_ACK,4)){
				
				JTC_COMM_SM_stateSwitch(sm,JTC_COMM_SM_STATE_IDEL);
			}
			else if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_50ms)
			{
				sm->currState = JTC_COMM_SM_STATE_IDEL;
			}
			break;
			
		//----------------------------------------------------	
		case JTC_COMM_SM_STATE_ERR:
			if(JTC_COMM_SM_tickElapsed(sm) > JTC_COMM_SM_TICK_100ms)
				sm->currState = JTC_COMM_SM_STATE_IDEL;
			break;
		default:
			break;
	}
	return;
}
//------------------------------receive-----------------------------------------
///
void JTC_COMM_SM_clearRxFlag(JTC_COMM_SM *sm)
{
	sm->uartReceiveFlag = 0;
	return;
}
///
void JTC_COMM_SM_setRxFlag(JTC_COMM_SM *sm)
{
	sm->uartReceiveFlag = 1;
	return;
}
///
uint8_t JTC_COMM_SM_receiveNewFrame(JTC_COMM_SM *sm,uint8_t src,uint8_t cmd,uint16_t datalen)
{
	if(!sm->uartReceiveFlag)
		return 0;
	if(sm->uartReceiveSrc != src)
		return 0;
	if(sm->uartReceiveCmd != cmd)
		return 0;
	if(sm->uartReceiveDataLen != datalen && datalen != 0xFFFF)
		return 0;
	
	return 1;
}
///
void JTC_COMM_SM_setRxFrame(JTC_COMM_SM *sm,
								uint8_t src,
								uint8_t type,
								uint8_t cmd,
								uint8_t *dataBuf,
								uint16_t len)
{
	uint16_t i;
	
//	if(!JTC_COMM_SM_haveFrameToTx(sm))
//		return 1;
	
	sm->uartReceiveSrc = src;
	sm->uartReceiveType = type;
	sm->uartReceiveCmd = cmd;
	sm->uartReceiveDataLen = len;
	for(i=0; i< len; i++){
		sm->uartReceiveData[i] = dataBuf[i];
	}
	
	JTC_COMM_SM_setRxFlag(sm);
	return;
}
//------------------------------transmit-----------------------------------------
///
uint8_t JTC_COMM_SM_haveFrameToTx(JTC_COMM_SM *sm)
{
	if(sm->uartTransmitFlag != 0)
		return 1;
	return 0;
}
///
void JTC_COMM_SM_clearTxFlag(JTC_COMM_SM *sm)
{
	sm->uartTransmitFlag = 0;
	return;
}
///
void JTC_COMM_SM_setTxFlag(JTC_COMM_SM *sm)
{
	sm->uartTransmitFlag = 1;
	return;
}
///
void JTC_COMM_SM_setTxFrame(JTC_COMM_SM *sm,
							uint8_t dst,
							uint8_t type,
							uint8_t cmd,
							uint8_t *dataBuf,
							uint16_t len)
{
	uint16_t i;
	
//	if(!JTC_COMM_SM_haveFrameToTx(sm))
//		return 1;
	
	sm->uartTransmitDst = dst;
	sm->uartTransmitType = type;
	sm->uartTransmitCmd = cmd;
	sm->uartTransmitDataLen = len;
	for(i=0; i< len; i++){
		if(dataBuf == 0)
			sm->uartTransmitData[i] = 0;
		else
			sm->uartTransmitData[i] = dataBuf[i];
	}
	
	JTC_COMM_SM_setTxFlag(sm);
	return;
}
///
uint8_t JTC_COMM_SM_takeTxFrame(JTC_COMM_SM *sm,
									uint8_t *dst,
									uint8_t *type,
									uint8_t *cmd,
									uint8_t *readDataBuf,
									uint16_t *len)
{
	uint16_t i;
	
	if(!dst || !type || !cmd || !readDataBuf || !len)
		return 1;
	
	if(!JTC_COMM_SM_haveFrameToTx(sm))
		return 1;
	
	*dst = sm->uartTransmitDst;
	*type = sm->uartTransmitType;
	*cmd = sm->uartTransmitCmd;
	*len = sm->uartTransmitDataLen;
	for(i=0; i< sm->uartTransmitDataLen; i++){
		readDataBuf[i] = sm->uartTransmitData[i];
	}
	
	JTC_COMM_SM_clearTxFlag(sm);
	
	return 0;
}
//-----------------------------------------------------------------------






///EOF
